<template>
	<view class="com-calendar">
		<view class="weeks">
			<view class="week-item" v-for="(item, index) in weeks" :key="index">{{ item }}</view>
		</view>
		<scroll-view scroll-y class="scroll">
			<view class="calendar-lists">
				<view class="calendar-item" v-for="(calendar, index) in calendars" :key="index">
					<view class="calendar-title">{{ calendar.year }}年{{ calendar.month }}月</view>
					<view class="calendar-days">
						<view class="item-date-wrap" v-for="item in calendar.days" :key="item.date">
							<view class="item-day-wrap" :class="[
								{'item-day-wrap-select': item.selected && item.show}, 
								{'item-start': item.start && item.show && !item.end}, 
								{'item-end': item.end && item.show && !item.start},
								{'item-start-end': item.start && item.end},
								{ 'start-end': item.start && item.end && item.show },
								{ 'today-item': item.today }
								]">
								<view v-if="item.show" class="item-day" :class="[
									{'disabled-item-day': item.disabled}, 
									]" @click="handleSelect(item)">
									<view class="day">{{ item.day }}</view>
									<!-- <view v-if="item.today && !item.start && !item.end && !item.obtain" class="today">今天</view>
									<view v-if="item.start && !item.end" class="active-day-text">开始</view>
									<view v-if="item.end && !item.start" class="active-day-text">结束</view>
									<view v-if="item.end && item.start" class="active-day-text">一天</view>
									<view v-if="item.obtain" class="active-day-text">拿到</view>
									<view v-if="item.return" class="active-day-text">归还</view> -->
								</view>
							</view>
						</view>
					</view>
				</view>
			</view>
		</scroll-view>
	</view>
</template>

<script>
	export default {
		name: "com-calendar2",
		props: {
			// 开始年份
			startYear: {
				type: Number,
				default: 0,
			},
			// 开始月份
			startMonth: {
				type: Number,
				default: 0,
			},
			// 最多选择的天数
			maxDays: {
				type: Number,
				default: 90,
			},
			// 选择的日期
			selected: {
				type: Array,
				default: () => [],
			},
			// 禁用的天数
			disabledNum: {
				type: Number,
				default: 0,
			},
			// 禁用日期
			disabledDate: {
				type: Array,
				default: () => [],
			},
			// 可选择日期
			range: {
				type: Array,
				default: () => [],
			}
		},
		data() {
			return {
				weeks: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
				calendars: [],
				year: 0,
				month: 0,

				startDate: '', // 开始日期
				endDate: '', // 结束日期
				currentSelected: [], // 当前选择的日期
			};
		},
		watch: {
			selected(val) {
				// 初始化选择日期
				this.initSelectDate()
				// 初始化日历
				this.init()
			},
			range(val) {
				this.init()
			}
		},
		mounted() {
			// 初始化选择日期
			this.initSelectDate()
			// 初始化日历
			this.init()
		},
		methods: {
			// 初始化选择日期
			initSelectDate() {
				if (this.selected && this.selected.length > 1) {
					let status = this.checkDisabled(this.selected[0], this.selected[1])
					if (!status) {
						this.startDate = ''
						this.endDate = ''
						this.currentSelected = []
						uni.showToast({
							icon: 'none',
							title: '档期不满足，请重新选择'
						})
						return
					} else {
						this.startDate = this.selected[0] || ''
						this.endDate = this.selected[1] || ''
						this.currentSelected = [...this.selected]
					}
				}
			},
			// 选择日期
			handleSelect(item) {
				if (item.disabled) {
					uni.showToast({
						icon: 'none',
						title: '该日期不可选'
					})
					return
				}
				// 如果开始日期和结束日期都已选，择重置日历选择状态
				if (this.startDate && this.endDate) {
					this.startDate = ''
					this.endDate = ''
					this.currentSelected = []
					this.calendars = this.calendars.map(calendar => {
						calendar.days = calendar.days.map(day => {
							day.selected = false
							day.start = false
							day.end = false
							day.obtain = false
							day.return = false
							return day
						})
						return calendar
					})
				}

				// 如果开始日期为空，则赋值到开始日期
				if (this.startDate === '') {
					this.startDate = item.date
					item.start = true
				} else {
					
					let status = this.checkDisabled(this.startDate, item.date)
					if (!status) {
						uni.showToast({
							icon: 'none',
							title: '档期不满足，请重新选择'
						})
						return
					}
				}
				
				// 选择的日期
				this.currentSelected = [this.startDate, this.endDate]


				if (this.startDate && this.endDate) {
					this.changeSelected()
				}
				this.$emit('change', this.currentSelected)
			},
			// 检查日期是否可选
			checkDisabled(date1, date2) {
				// 如果开始日期不为空，判断选择的日期是否是开始日期之后。
				const future = this.$dayjs(date2).isAfter(date1)
				
				let endDate = '';
				let startDate = '';
				if (future) {
					startDate = date1
					endDate = date2
				} else if (!future && date1 === date2) {
					startDate = date1
					endDate = date2
				} else {
					endDate = date1
					startDate = date2
				}
				
				let result = [];
				let currentDate = this.$dayjs(startDate);
				let endDate2 = this.$dayjs(endDate);
				let status = true
				// 遍历直到当前日期超过结束日期
				while (currentDate.isBefore(endDate2) || currentDate.isSame(endDate2, 'day')) {
					if (!this.range.includes(currentDate.format('YYYY-MM-DD'))) {
						status = false
					}
					currentDate = currentDate.add(1, 'day');
				}
				
				if (status) {
					this.startDate = startDate
					this.endDate = endDate
				} 
				
				return status
			},
			changeSelected() {
				this.calendars = this.calendars.map(calendar => {
					calendar.days = calendar.days.map(day => {
						// 是否是选择的日期
						day.selected = this.$dayjs(day.date).isBetween(this.$dayjs(this.currentSelected[
							1]), this.$dayjs(this.currentSelected[0]), null, '[]');
						// 是否是选择日期的开始日期
						day.start = this.currentSelected[0] === day.date
						// 是否是选择日期的结束日期
						day.end = this.currentSelected[1] === day.date
						// 拿到日期是选择日期的前一天
						day.obtain = this.$dayjs(this.currentSelected[0]).subtract(1, 'day').isSame(day
							.date, 'day')
						// 归还日期是选择的结束日的后一天
						day.return = this.$dayjs(this.currentSelected[1]).add(1, 'day').isSame(day.date,
							'day')
						return day
					})
					return calendar
				})
			},
			// 初始化日历
			init() {
				this.year = this.startYear ? this.startYear : this.$dayjs().year()
				this.month = this.startMonth ? this.startMonth : this.$dayjs().month() + 1
				// 定义起始日期和结束日期
				const startDate = this.$dayjs(`${this.year}-${this.month}-01`);
				const endDate = this.$dayjs(`${this.year}-${this.month}-01`).add(this.maxDays, 'day').format('YYYY-MM-DD');

				// 初始化结果数组
				const result = [];

				// 当前日期从起始日期开始
				let currentDate = startDate;

				// 遍历直到当前日期超过结束日期
				while (currentDate.isBefore(endDate) || currentDate.isSame(endDate, 'month')) {
					result.push({
						year: currentDate.year(),
						month: currentDate.month() + 1,
						date: currentDate.format('YYYY-MM')
					});
					currentDate = currentDate.add(1, 'month');
				}

				let lists = []
				for (var i = 0; i < result.length; i++) {
					const item = result[i]
					const days = this.getCalendarData(item.year, item.month);

					let data = {
						year: item.year,
						month: item.month,
						days: days
					}
					lists.push(data)
				}

				this.calendars = lists
			},
			// 使用dayjs制作一个日历数据，并且标记出今天，已经过去的日期，和未来的日期，以及最少4天物流时间，不可选，以及选择的日期，以及最多选择的天数
			getCalendarData(year, month) {
				const days = [];
				const firstDay = this.$dayjs(`${year}-${month}-01`).day();
				const lastDay = this.$dayjs(`${year}-${month}-01`).endOf('month').date();

				// 获取当月的日期
				for (let i = 0; i < firstDay; i++) {
					const day = this.$dayjs(`${year}-${month}-01`).subtract(firstDay - i, 'day').format('DD');
					days.push({
						day: Number(day), // 日
						show: false, // 是否显示
						// 获取日期
						date: `${year}-${month < 11 ? '0'+ (month-1) : (month-1)}-${day}`, // 日期
						month, // 月
						year, // 年
						today: false, // 是否是今天
						future: false, // 是否是未来的日期
						disabled: true, // 是否是禁止的日期
						selected: false, // 是否是选择的日期
						start: false, // 是否是选择日期的开始日期
						end: false, // 是否是选择日期的结束日期
						obtain: false, // 拿到日期是选择日期的前一天
						return: false, // 归还日期是选择的结束日的后一天
					});
				}
				for (let i = 1; i <= lastDay; i++) {
					days.push({
						day: i, // 日
						show: true, // 是否显示
						date: `${year}-${month < 10 ? '0'+ month : month}-${i < 10 ? '0'+ i : i}`, // 日期
						month, // 月
						year, // 年
						today: false, // 是否是今天
						future: false, // 是否是未来的日期
						disabled: true, // 是否是禁止的日期
						selected: false, // 是否是选择的日期
						start: false, // 是否是选择日期的开始日期
						end: false, // 是否是选择日期的结束日期
						obtain: false, // 拿到日期是选择日期的前一天
						return: false, // 归还日期是选择的结束日的后一天
					});
				}
				// 获取今天的日期的位置
				const today = this.$dayjs().format('YYYY-MM-DD');
				const todayIndex = days.findIndex((item) => item.day === this.$dayjs(today).date());
				// 获取未来日期的位置
				const future = this.$dayjs().add(1, 'day').format('YYYY-MM-DD');
				const futureIndex = days.findIndex((item) => item.day === this.$dayjs(future).date());
				const now = this.$dayjs(); // 当前时间
				const fourDaysLater = now.add(this.disabledNum - 1, 'day');

				this.days = days.map((item, index) => {
					let data = {
						...item
					}
					// 是否是今天
					item.today = item.date === this.$dayjs().format('YYYY-MM-DD')
					// 是否是未来
					item.future = this.$dayjs(item.date).isAfter(now)
					// 是否是禁止的日期
					// item.disabled = this.$dayjs(item.date) && this.$dayjs(item.date).isBefore(fourDaysLater) || this.disabledDate && this.disabledDate.includes(item.date);
					item.disabled = !this.range.includes(item.date);


					if (this.currentSelected.length) {
						// 是否是选择的日期
						item.selected = this.currentSelected[1] ? this.$dayjs(item.date).isBetween(this.$dayjs(this.currentSelected[1]), this.$dayjs(this.currentSelected[0]), null, '[]') : item.selected;
						// 是否是选择日期的开始日期
						item.start = this.currentSelected[0] === item.date
						// 是否是选择日期的结束日期
						item.end = this.currentSelected[1] && this.currentSelected[1] === item.date
						// 拿到日期是选择日期的前一天
						item.obtain = this.$dayjs(this.currentSelected[0]).subtract(1, 'day').isSame(item.date,
							'day')
						// 归还日期是选择的结束日的后一天
						item.return = this.currentSelected[1] ? this.$dayjs(this.currentSelected[1]).add(1, 'day').isSame(item.date, 'day') : item.return
					}

					return item
				})

				return this.days

			},
		}
	}
</script>

<style lang="scss" scoped>
	.com-calendar {

		.weeks {
			position: relative;
			gap: 8rpx;
			display: grid;
			padding: 0 32rpx;
			grid-template-columns: repeat(7, 1fr);

			.week-item {
				flex: 1;
				height: 92rpx;
				font-size: 28rpx;
				font-weight: 400;
				line-height: 44rpx;
				color: rgba(0, 0, 0, 0.6);

				display: flex;
				align-items: center;
				justify-content: center;
				box-sizing: border-box;
			}

			&::after {
				position: absolute;
				content: '';
				left: 50%;
				right: 0;
				bottom: 0;
				width: 96%;
				transform: translateX(-50%);
				// border-bottom: 1px solid #e1e1e1;
			}
		}


		.scroll {
			width: 100%;
			height: 50vh;
		}


		.calendar-lists {
			display: flex;
			gap: 32rpx;
			padding: 0 32rpx;
			padding-top: 32rpx;
			flex-direction: column;

			.calendar-item {
				position: relative;
				width: 100%;
				padding-bottom: 24rpx;

				&::after {
					position: absolute;
					content: '';
					left: 50%;
					right: 0;
					bottom: 0;
					width: 96%;
					transform: translateX(-50%);
					// border-bottom: 1px solid #e1e1e1;
				}

				&:last-child {
					&::after {
						border: none;
					}
				}

				.calendar-title {
					font-size: 28rpx;
					font-weight: 500;
					line-height: 36rpx;
					text-align: left;
					// padding-top: 24rpx;
					padding-bottom: 16rpx;
				}

				.calendar-days {
					// gap: 16rpx;
					display: grid;
					grid-template-columns: repeat(7, 1fr);
					align-items: center;
					box-sizing: border-box;
					gap: 8rpx;
				}

				.item-date-wrap {
					position: relative;
					height: 116rpx;
					display: flex;
					align-items: center;
					justify-content: center;
					gap: 8rpx;
					// border: 1px solid var(--primary-color);
				}


				.item-day-wrap {
					width: 100%;
					height: 100%;
					box-sizing: border-box;
					display: flex;
					align-items: center;
					justify-content: center;
				}

				.item-day-wrap-select {
					position: relative;
					z-index: 2;

					&::after {
						position: absolute;
						content: '';
						top: 50%;
						left: 0;
						right: 0;
						bottom: 0;
						width: 110%;
						height: 100%;
						z-index: -1;
						transform: translateY(-50%);
						background-color: #ffe8e4;
					}
				}

				.disabled-item-day {
					color: rgba(0, 0, 0, 0.26);
				}

				.today-item {
					color: var(--primary-color);
				}

				.item-start,
				.item-end {
					z-index: 9;
					width: 100%;
					height: 100%;
					color: #FFFFFF;

					&::before {
						position: absolute;
						content: '';
						top: 50%;
						left: 50%;
						right: 0;
						bottom: 0;
						width: 100%;
						height: 100%;
						z-index: 0;
						overflow: hidden;
						// background: linear-gradient(155.31deg, #A3A2B2 49.03%, #C8C8D1 117.81%);
						background: var(--gradient-color-vertical);
						transform: translateX(-50%) translateY(-50%);
					}
				}

				.item-start {
					&:before {
						border-radius: 8rpx 0 0 8rpx;
					}

					&::after {
						transform: translateX(10%) translateY(-50%);
					}
				}

				.item-end {
					z-index: 10;

					&:before {
						border-radius: 0 8rpx 8rpx 0;
					}

					&::after {
						transform: translateX(-10%) translateY(-50%);
					}
				}

				.item-start-end {
					z-index: 9;
					width: 100%;
					height: 100%;
					color: #FFFFFF;

					&::before {
						position: absolute;
						content: '';
						top: 50%;
						left: 50%;
						right: 0;
						bottom: 0;
						width: 100%;
						height: 100%;
						z-index: 0;
						overflow: hidden;
						border-radius: 8rpx;
						background-color: var(--primary-color);
						transform: translateX(-50%) translateY(-50%);
					}

					&::after {
						background-color: transparent;
					}
				}

				.start-end {
					&::after {
						width: 0%;
					}
				}

				.obtain-return {
					border: 1px solid var(--primary-color);
					background-color: #eae9ff78;
				}

				.item-day {
					z-index: 9;
					width: 100%;
					height: 100%;
					padding: 12rpx 0;
					border-radius: 6rpx;
					box-sizing: border-box;
					display: flex;
					align-items: center;
					flex-direction: column;
					justify-content: center;
					// transform: translateX(-50%) translateY(-50%);
				}


				.day {
					z-index: 9;
					font-size: 32rpx;
					font-weight: 600;
					line-height: 48rpx;
					text-align: center;
				}

				.today {
					color: #999999;
					font-size: 22rpx;
					font-weight: 500;
					line-height: 32rpx;
					text-align: center;
				}

				.active-day-text {
					color: #000000;
					font-size: 22rpx;
					font-weight: 500;
					line-height: 32rpx;
					text-align: center;
				}


			}
		}
	}
</style>